home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / QuickDraw3D 1.6 SDK / Mac SampleCode New for 1.6 / WorldRayPickSample / Source / WRay_Document.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-20  |  9.5 KB  |  435 lines  |  [TEXT/CWIE]

  1. /* 
  2.  *    WRay_Document.c
  3.  *
  4.  *    QuickDraw 3D 1.6 Sample
  5.  *    Robert Dierkes
  6.  *
  7.  *     07/28/98    RDD        Created.
  8.  */
  9.  
  10. /*------------------*/
  11. /*    Include Files    */
  12. /*------------------*/
  13. #include "QD3D.h"
  14. #include "QD3DCamera.h"
  15. #include "QD3DGroup.h"
  16. #include "QD3DMath.h"
  17. #include "QD3DTransform.h"
  18. #include "QD3DView.h"
  19.  
  20. #include "WRay_Document.h"
  21. #include "WRay_Error.h"
  22. #include "WRay_Main.h"
  23. #include "WRay_Memory.h"
  24. #include "WRay_Scene.h"
  25.  
  26. #include <math.h>
  27.  
  28. /*----------------------*/
  29. /*        Macros            */
  30. /*----------------------*/
  31. #define    uIsZero(v)                (((v) >= -kQ3RealZero) && ((v) <= kQ3RealZero))
  32.  
  33.  
  34. /*------------------*/
  35. /*      Constants        */
  36. /*------------------*/
  37.  
  38. /*----------------------*/
  39. /*    Extern Declarations    */
  40. /*----------------------*/
  41.  
  42.  
  43. /*----------------------*/
  44. /*    Global Declarations    */
  45. /*----------------------*/
  46.  
  47.  
  48. /*----------------------*/
  49. /*    Local Prototypes    */
  50. /*----------------------*/
  51. static
  52. TQ3Status    Document_InitializeWindow(
  53.                 TDocumentPtr        pDocument);
  54. static
  55. TQ3Status    Document_DisposeWindow(
  56.                 TDocumentPtr        pDocument);
  57.  
  58.  
  59. /*
  60.  *    Document_Initialize
  61.  *
  62.  *    Returns kQ3False if anything fails while creating the document.
  63.  */
  64. TQ3Boolean Document_Initialize(
  65.             TDocumentPtr    pDocument) 
  66. {
  67.     DEBUG_ASSERT(pDocument != NULL, Document_Initialize);
  68.  
  69.     /*------------------------------*
  70.      * Common to this document only *
  71.      *------------------------------*/
  72.     pDocument->fWindow    = NULL;
  73.     pDocument->fView      = NULL;
  74.     pDocument->fModel     = NULL;
  75.  
  76.     Q3Matrix4x4_SetIdentity(&pDocument->fMatrix);
  77.  
  78.     /*================*
  79.      * Create objects *
  80.      *================*/
  81.  
  82.     /* Create window */
  83.     if (Document_InitializeWindow(pDocument) == kQ3Failure) {
  84.         return kQ3False;
  85.     }
  86.  
  87.     /* Create view(s) */
  88.     if ((pDocument->fView = Scene_NewView(pDocument->fWindow)) == NULL) {
  89.         return kQ3False;
  90.     }
  91.  
  92.     /* Create fModel */
  93.     if ((pDocument->fModel = Scene_NewModel()) == NULL) {
  94.         return kQ3False;
  95.     }
  96.  
  97.     /* Center the model */
  98.     if (Document_UpdateCamera(pDocument) == kQ3Failure) {
  99.         return kQ3False;
  100.     }
  101.  
  102.     return kQ3True;
  103. }
  104.  
  105.  
  106. /*
  107.  *    Document_Exit
  108.  */
  109. TQ3Boolean Document_Exit(
  110.             TDocumentPtr    pDocument)
  111. {
  112.     DEBUG_ASSERT(pDocument != NULL, Document_Exit);
  113.  
  114.     Object_Dispose_NULL(&pDocument->fView);
  115.     Object_Dispose_NULL(&pDocument->fModel);
  116.  
  117.     return (Document_DisposeWindow(pDocument) == kQ3Success)
  118.                 ? kQ3True
  119.                 : kQ3False;
  120. }
  121.  
  122.  
  123. #pragma mark -
  124.  
  125. /*
  126.  *    Document_Draw
  127.  */
  128. TQ3Status Document_Draw(
  129.             TDocumentPtr    pDocument)
  130. {
  131.     TQ3ViewObject    aView;
  132.     TQ3Status        status;
  133.     TQ3ViewStatus    viewStatus;
  134.  
  135.     DEBUG_ASSERT(pDocument != NULL, Document_Draw);
  136.  
  137.     aView = pDocument->fView;
  138.  
  139.     if (Q3View_StartRendering(aView) == kQ3Success) {
  140.         do {
  141.             status = Document_Submit_Objects(pDocument, aView);
  142.  
  143.             viewStatus = Q3View_EndRendering(aView);
  144.         } while (viewStatus == kQ3ViewStatusRetraverse);
  145.  
  146.         if (viewStatus != kQ3ViewStatusDone) {
  147.             return kQ3Failure;
  148.         }
  149.     } else {
  150.         ERROR_DEBUG_STR("Document_Draw: Q3View_StartRendering failed.");
  151.         return kQ3Failure;
  152.     }
  153.  
  154.     return kQ3Success;
  155. }
  156.  
  157.  
  158. /*
  159.  *    Document_Submit_Objects
  160.  *
  161.  * This assumes the model is already centered at the origin.
  162.  * No parameter checking is done.
  163.  */
  164. TQ3Status Document_Submit_Objects(
  165.             TDocumentPtr        pDocument,
  166.             TQ3ViewObject        view)
  167. {
  168.     DEBUG_ASSERT(pDocument != NULL, Document_Submit_Objects);
  169.     DEBUG_ASSERT(view != NULL,      Document_Submit_Objects);
  170.  
  171.     Q3MatrixTransform_Submit(&pDocument->fMatrix, view);
  172.  
  173.     return Q3DisplayGroup_Submit(pDocument->fModel, view);
  174. }
  175.  
  176.  
  177. #pragma mark -
  178.  
  179. /*
  180.  *    Document_InitializeWindow
  181.  */
  182. static
  183. TQ3Status Document_InitializeWindow(
  184.             TDocumentPtr    pDocument)
  185. {
  186.     WindowPtr    pWindow;
  187.  
  188.     DEBUG_ASSERT(pDocument != NULL, Document_InitializeWindow);
  189.  
  190.     pWindow = GetNewCWindow(kWindowRsrcID, NULL, kWindowOnTop);
  191.     pDocument->fWindow = pWindow;
  192.     if (pWindow == NULL) {
  193.         ERROR_DEBUG_STR("Document_InitializeWindow: GetNewCWindow failed.");
  194.         return kQ3Failure;
  195.     }
  196.  
  197.     SetPort((GrafPtr) pWindow);
  198.  
  199.     ShowWindow(pWindow);
  200.  
  201.     return kQ3Success;
  202. }
  203.  
  204.  
  205. /*
  206.  *    Document_DisposeWindow
  207.  */
  208. static
  209. TQ3Status Document_DisposeWindow(
  210.             TDocumentPtr    pDocument)
  211. {
  212.     DEBUG_ASSERT(pDocument != NULL, Document_DisposeWindow);
  213.  
  214.     if (pDocument->fWindow != NULL) {
  215.         DisposeWindow (pDocument->fWindow);
  216.         pDocument->fWindow = NULL;
  217.         return kQ3Failure;
  218.     }
  219.  
  220.     return kQ3Success;
  221. }
  222.  
  223.  
  224. #pragma mark -
  225.  
  226. /*
  227.  *    Document_UpdateCameraAspectRatio
  228.  */
  229. TQ3Status Document_UpdateCameraAspectRatio(
  230.             TDocumentPtr        pDocument,
  231.             Rect                *pPortRect)
  232. {
  233.     TQ3CameraObject        camera;
  234.     TQ3Status            status;
  235.     float                aspectRatioXToY;
  236.  
  237.     status = Q3View_GetCamera(pDocument->fView, &camera);
  238.     if ((status == kQ3Failure)  ||
  239.         (camera == NULL)) {
  240.         ERROR_DEBUG_STR("Document_UpdateCameraAspectRatio: Q3View_GetCamera failed.");
  241.         return status;
  242.     }
  243.  
  244.     status = Q3ViewAngleAspectCamera_GetAspectRatio(camera, &aspectRatioXToY);
  245.     if (status == kQ3Success) {
  246.         aspectRatioXToY    =    (float) (pPortRect->right  - pPortRect->left) / 
  247.                             (float) (pPortRect->bottom - pPortRect->top);
  248.         status = Q3ViewAngleAspectCamera_SetAspectRatio(camera, aspectRatioXToY);
  249.     }
  250.  
  251.     Object_Dispose_NULL(&camera);
  252.  
  253.     return status;
  254. }
  255.  
  256.  
  257. /*
  258.  *    Document_UpdateCamera
  259.  */
  260. TQ3Status Document_UpdateCamera(
  261.             TDocumentPtr        pDocument)
  262. {
  263.     TQ3CameraObject                camera;
  264.     TQ3CameraPlacement            placement;
  265.     TQ3CameraRange                range;
  266.     TQ3BoundingBox                 boundingBox;
  267.     float                         maxDimension;
  268.     float                         fieldOfView;
  269.     TQ3Status                    status;
  270.  
  271.     status = Q3View_GetCamera(pDocument->fView, &camera);
  272.     if ((status == kQ3Failure)  ||
  273.         (camera == NULL)) {
  274.         ERROR_DEBUG_STR("Document_UpdateCamera: Q3View_GetCamera failed.");
  275.         return kQ3Failure;
  276.     }
  277.  
  278.     if (Q3Object_IsType(camera, kQ3CameraTypeViewAngleAspect) == kQ3False) {
  279.         return kQ3Failure;
  280.     }
  281.  
  282.     /* Set FOV */
  283.     fieldOfView = kDefaultFieldOfView;
  284.     Q3ViewAngleAspectCamera_SetFOV(camera, fieldOfView);
  285.  
  286.     /* Get maxDimension and bounding box */
  287.     if (Document_GetMaximumDimension(pDocument, &maxDimension, &boundingBox) == kQ3Failure) {
  288.         return kQ3Failure;
  289.     }
  290.  
  291.     /* Set cameraLocation and pointOfInterest */
  292.     Q3Camera_GetPlacement(camera, &placement);
  293.  
  294.     Q3Point3D_Set(&placement.pointOfInterest,
  295.                     (boundingBox.max.x - boundingBox.min.x) / 2.0f + boundingBox.min.x,
  296.                     (boundingBox.max.y - boundingBox.min.y) / 2.0f + boundingBox.min.y,
  297.                     (boundingBox.max.z - boundingBox.min.z) / 2.0f + boundingBox.min.z);
  298.  
  299.     Q3Point3D_Set(&placement.cameraLocation,
  300.                     placement.pointOfInterest.x,
  301.                     placement.pointOfInterest.y,
  302.                     ((maxDimension / 2.5) / atan(fieldOfView / 2.0)));/* Using 2.5 brings camera closer */
  303.  
  304.     if ((status = Q3Camera_SetPlacement(camera, &placement)) == kQ3Success) {
  305.         /* Set hither and yon */
  306.         #define    kRangeMargin    (maxDimension / 2.0)
  307.  
  308.         range.hither = placement.cameraLocation.z - placement.pointOfInterest.z - kRangeMargin;
  309.         range.yon    = range.hither + maxDimension + kRangeMargin;
  310.  
  311.         status = Q3Camera_SetRange(camera, &range);
  312.     }
  313.  
  314.     Object_Dispose_NULL(&camera);
  315.  
  316.     return status;
  317. }
  318.  
  319.  
  320. /*
  321.  *    Document_BoundingBox
  322.  *
  323.  *    Computes bounding box for fModel.
  324.  */
  325. TQ3Status Document_BoundingBox(
  326.             TDocumentPtr        pDocument,
  327.             TQ3BoundingBox         *pBoundingBox)
  328. {
  329.     TQ3Status        status;
  330.     TQ3ViewStatus    viewStatus;
  331.     TQ3ViewObject    aView;
  332.  
  333.     if (pDocument == NULL) {
  334.         ERROR_DEBUG_STR("Document_BoundingBox: pDocument == NULL.");
  335.         return kQ3Failure;
  336.     }
  337.  
  338.     if (pBoundingBox == NULL) {
  339.         ERROR_DEBUG_STR("Document_BoundingBox: pBoundingBox == NULL.");
  340.         return kQ3Failure;
  341.     }
  342.  
  343.     aView = pDocument->fView;
  344.  
  345.     status = kQ3Success;
  346.  
  347.     if (Q3View_StartBoundingBox(aView, kQ3ComputeBoundsExact) == kQ3Failure) {
  348.         ERROR_DEBUG_STR("Document_BoundingBox: Q3View_StartBoundingBox failed.");
  349.         return kQ3Failure;
  350.     }
  351.  
  352.     do {
  353.         Document_Submit_Objects(pDocument,aView);
  354.  
  355.         viewStatus = Q3View_EndBoundingBox(aView, pBoundingBox);
  356.     }
  357.     while (viewStatus == kQ3ViewStatusRetraverse);
  358.  
  359.     if (viewStatus != kQ3ViewStatusDone) {
  360.         ERROR_DEBUG_STR("Document_BoundingBox: viewStatus != kQ3ViewStatusDone.");
  361.         status = kQ3Failure;
  362.     }
  363.  
  364.     return status;
  365. }
  366.  
  367.  
  368. /*
  369.  *    Document_GetMaximumDimension
  370.  *
  371.  *    Get model's maximum diagonal dimension.
  372.  */
  373. TQ3Status Document_GetMaximumDimension(
  374.     TDocumentPtr    pDocument,
  375.     float             *pMaxDimension,
  376.     TQ3BoundingBox    *pReturnedBoundingBox)
  377. {
  378.     TQ3BoundingBox        localBoundingBox,
  379.                         *pBoundingBox;
  380.     TQ3Vector3D            diagonalVector;
  381.     float                 dimension;
  382.  
  383.     #define            kAntiSingularity    0.0001
  384.  
  385.     if ((pDocument     == NULL) ||
  386.         (pMaxDimension == NULL)) {
  387.         ERROR_DEBUG_STR("Document_GetMaximumDimension: NULL parameter.");
  388.         return kQ3Failure;
  389.     }
  390.  
  391.     pBoundingBox = (pReturnedBoundingBox != NULL) ? pReturnedBoundingBox
  392.                                                   : &localBoundingBox;
  393.  
  394.     /* Compute length of diagonal for the bounding box */
  395.     if (Document_BoundingBox(pDocument, pBoundingBox) == kQ3Failure) {
  396.         ERROR_DEBUG_STR("Document_GetMaximumDimension: Document_BoundingBox failed.");
  397.         return kQ3Failure;
  398.     }
  399.  
  400.     /*
  401.      *  If we have a point or flat model, then the "boundingBox" would
  402.      *  end up being a "singularity" at the location of the point.  As
  403.      *  this bounding "box" is used in setting up the camera spec,
  404.      *  we get bogus input into QuickDraw 3D.
  405.      */
  406.     dimension = pBoundingBox->max.x - pBoundingBox->min.x;
  407.     if (uIsZero(dimension)) {
  408.         pBoundingBox->max.x += kAntiSingularity;
  409.         pBoundingBox->min.x -= kAntiSingularity;
  410.     }
  411.  
  412.     dimension = pBoundingBox->max.y - pBoundingBox->min.y;
  413.     if (uIsZero(dimension)) {
  414.         pBoundingBox->max.y += kAntiSingularity;
  415.         pBoundingBox->min.y -= kAntiSingularity;
  416.     }
  417.  
  418.     dimension = pBoundingBox->max.z - pBoundingBox->min.z;
  419.     if (uIsZero(dimension)) {
  420.         pBoundingBox->max.z += kAntiSingularity;
  421.         pBoundingBox->min.z -= kAntiSingularity;
  422.     }
  423.  
  424.     Q3Point3D_Subtract(&pBoundingBox->max,
  425.                        &pBoundingBox->min,
  426.                        &diagonalVector);
  427.  
  428.     *pMaxDimension = Q3Vector3D_Length(&diagonalVector);
  429.  
  430.     #undef    kAntiSingularity
  431.  
  432.     return kQ3Success;
  433. }
  434.  
  435.